/**
 * WTF Engine
 * 
 * License... etc.
 **
 * Widgets Implementation (Woosta GUI Toolkit)
 * 
 * Implementation of the base Widget and
 * some basic widgets deriving from it.
 * 
 * Basic notes:
 *  - Widget is a base class and contains only position, size
 *	  background colour. It has a default virtual keypress handler
 *  - Draw function is defined as End() . Paint() . Begin(), where Begin
 *    and End do the coordinate shifting
 *  - Paint draws the widget regardless of the current position
 *  - every widget has to define its Paint function.
 *
 * This file provides:
 *  - Base Widget Class
 * 	- Label, InputField, LogField Widgets	
 *  - Helper classes for storing information:
 * 		- StringBuffer - single-line text class
 **
 * Author: Mac Duy Hai, Sean Micklethwaite
 */

#ifndef __GUI_WIDGETS_H__
#define __GUI_WIDGETS_H__

#include "render.h"
#include "gui_font.h"
#include "input.h"
#include "interpolator.h"
#include "dator.h"
#include "observable.h"

namespace WtfGui {
	typedef WtfEngine::Setting<Font::tCacheRef>	tFont;
	
	/**
	 * Colours are now data objects themselves, and must be passed to widgets by
	 * reference. This means that we can store one colour object for all window
	 * backgrounds, so changing it will change all window backgrounds :)
	 **/
	typedef WtfEngine::Setting<WtfEngine::Interpolated<fVector4D, WtfEngine::Functions<fVector4D>::Linear> > tColourBase;
	
	class Colour : public tColourBase {
		public:
			Colour(const WtfEngine::String& sName, const fVector4D& colour = fVector4D())
			: tColourBase(sName, WtfEngine::Interpolated<fVector4D, WtfEngine::Functions<fVector4D>::Linear>(colour)) {
			};
			
			/// Assignment
			inline void operator = (const Colour& v){
				tColourBase::Init(v.Value);
			};
			inline void operator = (const fVector4D& v) {
				this->Value.Init(v);
			};
			
			inline fVector4D getValue() const {
				return this->Value.rInterpolator.isNull() ? this->Value.Value : this->Value.rInterpolator->getEnd();
			};
			inline fVector4D getRealValue() const {
				return this->Value.Value;
			};

			inline void Interpolate(const fVector4D& v, tScalar t, const WtfEngine::IFunctor<>::tRef& rFunc) {
				this->Value.Time = t;
				this->Value.Init(v, rFunc);
			};

			static Colour* Get(const WtfEngine::String& sName) {
				return GetType<Colour>(sName);
			};
			static Colour* Set(const WtfEngine::String& sName, const fVector4D& v) {
				return SetType<Colour>(sName, v);
			};

			DATA_LOADABLE(Colour, sizeof(Colour));
	};

	class WidgetContainer;
	
	/// The widget size is interpolated, so changes are smooth
	typedef struct InterpolatedWidgetVector: public WtfEngine::Interpolated<iVector2D, WtfEngine::Functions<fVector2D>::Linear> {
		const iVector2D& getValue() const {
			return (!rInterpolator.isNull() && rInterpolator->isRunning() ? rInterpolator->getEnd() : Value);
		};
		const iVector2D& getRealValue() const {
			return Value;
		};
		void setValue(const iVector2D& v) {
			this->Init(v);
		};
		void initValue(const iVector2D& v) {
			this->Value = v;
		};
	} tInterpolatedWidgetVector;
	typedef struct WidgetVector: public iVector2D {
		const iVector2D& getValue() const {
			return *this;
		};
		const iVector2D& getRealValue() const {
			return *this;
		};
		void setValue(const iVector2D& v) {
			*(iVector2D*)this = v;
		};
		void initValue(const iVector2D& v) {
			setValue(v);
		};
	} tNonInterpolatedWidgetVector;

	class IWidgetLayout: public virtual WtfEngine::IObservable {
		public:
			/// Describes the widget padding - format is:
			/// [[Left, Top], [Right, Bottom]]
			typedef VectorType<iVector2D, 2>::tType	tPadding;

			virtual const iVector2D& getSize() const = 0;
			virtual iVector2D getInnerSize() const = 0;
			virtual const iVector2D& getPosition() const = 0;
			virtual tPadding getPadding() const = 0;

			virtual void initSize(const iVector2D& v) {
				NotifyObservers();
			};
			virtual void setSize(const iVector2D&) {
				NotifyObservers();
			};
			virtual void setPosition(const iVector2D&) {
				NotifyObservers();
			};
			virtual void setPadding(const tPadding& v) {
				NotifyObservers();
			};

			virtual const iVector2D& getRealSize() const = 0;
			virtual iVector2D getRealInnerSize() const = 0;
			virtual const iVector2D& getRealPosition() const = 0;

			GC_INTERFACE(IWidgetLayout);
	};

	template <class tWidgetSize = InterpolatedWidgetVector, class tWidgetPosition = WidgetVector>
	class WidgetLayout: public IWidgetLayout, public WtfEngine::GcObject {
		tWidgetSize		mSize;
		tWidgetPosition	mPos;
		tPadding		mPadding;

		public:
			WidgetLayout() {};
			explicit WidgetLayout(const IWidgetLayout::tRef& rPrevious) {
				mSize.initValue(rPrevious->getSize());
				mPos.initValue(rPrevious->getPosition());
			};

			virtual const iVector2D& getSize() const {
				return mSize.getValue();
			};
			virtual iVector2D getInnerSize() const {
				return getSize() - (mPadding[0] + mPadding[1]);
			};
			virtual const iVector2D& getPosition() const {
				return mPos.getValue();
			};
			virtual tPadding getPadding() const {
				return mPadding;
			};

			virtual void initSize(const iVector2D& v) {
				if(v != mSize.getValue()) {
					mSize.initValue(v);
					IWidgetLayout::initSize(v);
				};
			};
			virtual void setSize(const iVector2D& v) {
				if(v != mSize.getValue()) {
					mSize.setValue(v);
					IWidgetLayout::setSize(v);
				};
			};
			virtual void setPosition(const iVector2D& v) {
				if(v != mPos.getValue()) {
					mPos.setValue(v);
					IWidgetLayout::setPosition(v);
				};
			};
			virtual void setPadding(const tPadding& v) {
				if(v != mPadding) {
					iVector2D vSize = getSize();
					tPadding vDiff = v - mPadding;
					mPadding = v;

					// Change size by change in padding to simulate interpolation
					mSize.initValue(vSize - (vDiff[0] + vDiff[1]));
					setSize(vSize);
				};
			};

			virtual const iVector2D& getRealSize() const {
				return mSize.getRealValue();
			};
			virtual iVector2D getRealInnerSize() const {
				return getRealSize() - (mPadding[0] + mPadding[1]);
			};
			virtual const iVector2D& getRealPosition() const {
				return mPos.getRealValue();
			};
			

			GC_AUTOSIZE(WidgetLayout);
	};


	class AbstractWidget: public virtual WtfEngine::IRenderable {
	protected:
		AbstractWidget * mpDelegate;

		AbstractWidget();
		inline explicit AbstractWidget(AbstractWidget* pDelegate): mpDelegate(pDelegate) {
		};

	public:
		//// Methods
		virtual void Draw(float d) {
			mpDelegate->Draw(d);
		};
		void Render() {
			Draw(0.01);
		};

		inline void Move(int x, int y) {
			Move(iVector2D(x, y));
		};
		inline void Move(const iVector2D& vPos) {
			getLayout()->setPosition(vPos);
		};

		inline void Resize(int w, int h) {
			Resize(iVector2D(w, h));
		};
		virtual void Resize(const iVector2D& vSize) {
			mpDelegate->Resize(vSize);
		};

		//// Properties
		virtual WidgetContainer* getParent() const {
			return mpDelegate->getParent();
		};

		virtual bool isSelected() {
			return mpDelegate->isSelected();
		};

		virtual const IWidgetLayout::tRef& getLayout() const {
			return mpDelegate->getLayout();
		};
		virtual void setLayout(const IWidgetLayout::tRef& rLayout) {
			mpDelegate->setLayout(rLayout);
		};

		inline const iVector2D&	getPosition() const {
			return getLayout()->getPosition();
		};

		inline const iVector2D&	getSize() const{
			return getLayout()->getSize();
		};
		inline iVector2D			getInnerSize() const{
			return getLayout()->getInnerSize();
		};
		virtual void	setInnerSize(const iVector2D& vSize) {
			mpDelegate->setInnerSize(vSize);
		};

		inline const iVector2D& getRealSize() const {
			return getLayout()->getRealSize();
		};
		inline iVector2D getRealInnerSize() const {
			return getLayout()->getRealInnerSize();
		};
		inline const iVector2D& getRealPosition() const {
			return getLayout()->getRealPosition();
		};

		//// Events
		/// Called when the widget is inserted into a container
		virtual void OnInsert(WidgetContainer* pParent) {
			mpDelegate->OnInsert(pParent);
		};

		virtual void OnResize() {
			mpDelegate->OnResize();
		};
		virtual void OnParentResize() {
			mpDelegate->OnParentResize();
		};

		virtual void OnSelect() {
			mpDelegate->OnSelect();
		};
		virtual void OnDeselect() {
			mpDelegate->OnDeselect();
		};
		
		// Input events - return true if event is handled
		virtual bool OnKeyPress(int key, int flags) {
			return mpDelegate->OnKeyPress(key, flags);
		};
		virtual bool OnKeyDown(int key) {
			return mpDelegate->OnKeyDown(key);
		};
		virtual bool OnKeyUp(int key) {
			return mpDelegate->OnKeyUp(key);
		};
		
		virtual bool OnMouseDown(const iVector2D& vPos, WtfEngine::tMouseButton btn) {
			return mpDelegate->OnMouseDown(vPos, btn);
		};
		virtual bool OnMouseUp(const iVector2D& vPos, WtfEngine::tMouseButton btn) {
			return mpDelegate->OnMouseUp(vPos, btn);
		};
		virtual bool OnMouseOver(const iVector2D& vPos, const iVector2D& vDelta) {
			return mpDelegate->OnMouseOver(vPos, vDelta);
		};
		virtual bool OnMouseOut(const iVector2D& vPos, const iVector2D& vDelta) {
			return mpDelegate->OnMouseOut(vPos, vDelta);
		};
		virtual bool OnMouseMove(const iVector2D& vPos, const iVector2D& vDelta) {
			return mpDelegate->OnMouseMove(vPos, vDelta);
		};

		GC_INTERFACE(AbstractWidget);
	};


	/**
	 * Widget Class.
	 * 
	 * A basic drawable object, capable of receiving events. 
	 */
	class Widget: public AbstractWidget, public WtfEngine::GcObject {
		public:
			//// Widget Backgrounds

			class IBackground: public virtual WtfEngine::IGcObject {
			public:
				virtual void Render(const iVector2D& vSize) = 0;

				GC_INTERFACE(IBackground);
			};

			class NoBackground: public virtual IBackground, public WtfEngine::GcObject {
			public:
				virtual void Render(const iVector2D& vSize) { };

				GC_AUTOSIZE(NoBackground);
			};

			class ColourBackground: public NoBackground {
			protected:
				Colour::tRef mrColour;

			public:
				typedef struct ColourBackgroundCreationOptions {
					Colour::tRef rColour;

					ColourBackgroundCreationOptions();
				} tCreationOptions;

				inline ColourBackground(const tCreationOptions& opts)
					: mrColour(opts.rColour) {
				};

				virtual void Render(const iVector2D& vSize);

				inline const Colour::tRef& getColour() {
					return mrColour;
				};
				inline void setColour(const Colour::tRef& rColour) {
					mrColour = rColour;
				};

				GC_AUTOSIZE(ColourBackground);
			};

			class RoundedCornerBackground: public ColourBackground {
				typedef VectorType<iVector2D, 2>::tType tRadii;

				tRadii mvRadii;

			public:
				typedef struct RoundedCornerBackgroundCreationOptions: public ColourBackground::tCreationOptions {
					/// The size of each corner, specified as [[left, right], [top, bottom]]
					tRadii vRadii;

					/// Default parameters
					RoundedCornerBackgroundCreationOptions();
				} tCreationOptions;

				inline RoundedCornerBackground(const tCreationOptions& opts = tCreationOptions())
					: ColourBackground(opts), mvRadii(opts.vRadii) {
				};

				virtual void Render(const iVector2D& vSize);

				GC_AUTOSIZE(RoundedCornerBackground);
			};


			/// Backgrounds are given as settings
			typedef WtfEngine::Setting<IBackground::tRef> tBackground;

		private:
			IWidgetLayout::tRef	mrLayout;
			
			tBackground::tRef mrBackground;
			Colour::tRef	mFgColour;
			
			int			mDragDropType;
			bool		mIsDragging;

		protected:
			WidgetContainer* mpParent;

			// Draw functions - each widget overrides the Paint function.
			void Begin();
			void End();
			virtual void Paint(float depthChange);
	
			virtual void SetupClipping() const;

			friend class WidgetContainer;

		public:
			// Constructors
			Widget(const WtfEngine::String& sName);
			Widget(const WtfEngine::String& sName, iVector2D vPosition, iVector2D vSize);
			
			virtual bool isSelected();
			
			inline WidgetContainer* getParent() const {
				return mpParent;
			};


			// Event handlers

			/// Called when the widget is inserted into a container
			virtual void OnInsert(WidgetContainer* pParent) {
				mpParent = pParent;
			};

			virtual void OnResize();
			virtual void OnParentResize() {};

			virtual void OnSelect() {};
			virtual void OnDeselect() {};
			
			// Input events - return true if event is handled
			virtual bool OnKeyPress(int key, int flags) { return false; };
			virtual bool OnKeyDown(int key) { return false; };
			virtual bool OnKeyUp(int key) { return false; };
			
			virtual bool OnMouseDown(const iVector2D& vPos, WtfEngine::tMouseButton btn);
			virtual bool OnMouseUp(const iVector2D& vPos, WtfEngine::tMouseButton btn);
			virtual bool OnMouseOver(const iVector2D& vPos, const iVector2D& vDelta);
			virtual bool OnMouseOut(const iVector2D& vPos, const iVector2D& vDelta);
			virtual bool OnMouseMove(const iVector2D& vPos, const iVector2D& vDelta);
			
			
			/// Draw := End . Paint . Begin
			void Draw(float d) {
				Begin(); Paint(d); End();
			};
			
			void Resize(const iVector2D& vSize) {
				mrLayout->setSize(vSize);
				mpDelegate->OnResize();
			};
			void Resize(const iVector2D& vSize, const iVector2D& vPadding){
				mrLayout->setPadding(IWidgetLayout::tPadding(vPadding, vPadding));
				Resize(vSize);
			};
			
			/// Returns the proper size of the widget's child elements. Used
			/// to implement scrolling and automatic sizing.
			virtual iVector2D getContentSize() const {
				return iVector2D();
			};
			
			inline void Expand() {
				setInnerSize(getContentSize());
			};


			// Properties

			const IWidgetLayout::tRef& getLayout() const {
				return mrLayout;
			};
			void setLayout(const IWidgetLayout::tRef& rLayout) {
				mrLayout = rLayout;
			};

			void	setInnerSize(const iVector2D& vSize) {
				Resize(vSize + mrLayout->getPadding()[0] + mrLayout->getPadding()[1]);
			};

			template <int i>
			iVector2D getPadding2D() const {
				return mrLayout->getPadding()[i];
			};
			template <int i>
			void setPadding2D(const iVector2D& padding) {
				IWidgetLayout::tPadding p = mrLayout->getPadding();
				p[i] = padding;
				mrLayout->setPadding(p);
				OnResize();
			};

			IWidgetLayout::tPadding getPadding() const {
				return mrLayout->getPadding();
			};
			void setPadding(const IWidgetLayout::tPadding& padding) {
				mrLayout->setPadding(padding);
				OnResize();
			};

			const tBackground::tRef& getBackground() {
				return mrBackground;
			};
			void setBackground(const tBackground::tRef& rBg) {
				mrBackground = rBg;
			};

			void SetFgColour(const Colour::tRef& colour, bool bInterpolate = true);

			const Colour::tRef& getFgColour() const {
				return mFgColour;
			};

			void setDragDropType(int i) {
				mDragDropType = i;
			};

			void Remove();
			
		private:
			void _SetFgColour(const Colour::tRef& colour){
				mFgColour = colour;
			};

			GC_AUTOSIZE(Widget);
	};

	
	/**
	 * Base class for widget wrappers (decorators)
	 **/
	class WidgetWrapper: public AbstractWidget, public WtfEngine::GcObject {
		AbstractWidget::tRef mrWidget;

	public:
		inline WidgetWrapper(AbstractWidget* pWidget):
			AbstractWidget(pWidget), mrWidget(pWidget) {
		};

		inline AbstractWidget::tRef getWidget() const {
			return mrWidget;
		};
	};

	
	/**
	 * Basic container class, for composition of multiple widgets
	 **/
	class WidgetContainer : public Widget {
		protected:
			typedef	std::list<AbstractWidget::tRef>	tChildList;
			
			tChildList mChildren;		///< List of child widgets
			AbstractWidget::tRef mrActiveChild;	///< Currently selected child widget
		
			virtual void Paint(float d);
			
			friend class Widget;
			
		public:
			// Constructors
			WidgetContainer(const WtfEngine::String& sName) : Widget(sName) {};
			WidgetContainer(const WtfEngine::String& sName, iVector2D vPosition, iVector2D vSize)
				: Widget(sName, vPosition, vSize) {};
			
			/// Places a child at the back of the list
			virtual void AddChild(const AbstractWidget::tRef& rChild);
			
			/// Removes a child from the list
			virtual void RemoveChild(const AbstractWidget::tRef& rChild);
			
			virtual bool HasChild(const AbstractWidget::tRef& rChild);

			virtual void Clear() {
				mChildren.clear();
				mrActiveChild.Destroy();
				OnChildResize();
			};

			/// Sends a child to the front of the display
			void SendToFront(const AbstractWidget::tRef& rChild);
			/// Sends a child to the back of the display
			void SendToBack(const AbstractWidget::tRef& rChild);
			
			/// Marks the specified child as selected
			virtual void Select(const AbstractWidget::tRef& rChild, bool bPropagate = true);
			
			/// Cycles to the next child widget of the specified type
			template <class T>
			void NextChild() {
				tChildList::iterator	i(
					std::find(mChildren.begin(), mChildren.end(), mrActiveChild));
				if(i == mChildren.end()) {
					if(!mChildren.empty())
						Select(*mChildren.begin());
				} else {
					while((++i != mChildren.end()) && !dynamic_cast<T*>(&**i)) {};
					if(i != mChildren.end())
						Select(*i);
				};
			};
			template <class T>
			void PreviousChild() {
				tChildList::iterator	i(
					std::find(mChildren.begin(), mChildren.end(), mrActiveChild));
				if(i == mChildren.end()) {
					if(!mChildren.empty())
						Select(*--i);
				} else {
					while((i != mChildren.begin()) && !dynamic_cast<T*>(&**--i)) {};
					if(i != mChildren.end())
						Select(*i);
				};
			};

			virtual iVector2D getContentSize();

			/// This default event handler calls OnParentResize() on all children.
			virtual void OnResize();

			/// Called when a child element is resized. Care must be taken when this event
			/// results in resizing of this container, as calls to OnParentResize() may result
			/// in another child resize, resulting in an infinite loop. If this functionality is
			/// required, OnResize() should be overridden.
			virtual void OnChildResize() {};

			virtual void OnSelect();
			virtual void OnDeselect();
			
			/// Sends key press to seleted child
			virtual bool OnKeyPress(int key, int flags);
			
			// Default mouse handlers: checks for overlap with children, and
			// sends the event to the first child which overlaps the pointer
			virtual bool OnMouseDown(const iVector2D& vPos, WtfEngine::tMouseButton btn);
			virtual bool OnMouseUp(const iVector2D& vPos, WtfEngine::tMouseButton btn);
			virtual bool OnMouseMove(const iVector2D& vPos, const iVector2D& vDelta);
			
			AbstractWidget::tRef GetChildAtPosition(const iVector2D& vPos);

			GC_AUTOSIZE(WidgetContainer);
	};
	
	
	/**
	 * Input interface - defines classes which accept input from the user.
	 * This interface is used to decide which elements to skip when selecting
	 * elements via the tab button.
	 **/
	class IInput
	{
		
	};
	
	
	/** 
	 * GUI Utilities.
	 * 
	 * Helper and Utility Classes for GUI elements.
	 */
	namespace Utils {
		/**
		 * StringBuffer is an implementation of a single-line WtfEngine::String buffer (using a gap buffer).
		 * 
		 * Abstraction Function:   text = buf[0..gap) ++ buf[MAX-len + gap..MAX]
		 */
		class StringBuffer {
			private:
				char*			buf;		// buffer storage
				int				max;		// buffer upper bound
				int				len;		// length of the stored WtfEngine::String
				int				gap;		// position of gap
				int				cursor;		// current cursor position in the WtfEngine::String (not buffer!)
				char*			text;		// pointer to result of toString()
				
				/// Moves the gap to specified position
				void moveGap(int pos);
				
			public:
				// De/constructors
				StringBuffer(int);
				~StringBuffer();
				
				/// Returns a character at specified position
				char charAt(int pos);
				
				/// Returns character at current cursor position
				char getChar();
				
				/// Deletes a character at current cursor position
				void deleteChar(int direction = 0);
				
				/// Inserts a character at current cursor position
				void insertChar(char ch);
				
				/// Moves cursor in specified direction
				void moveCursor(int direction);
				
				/// Erases the buffer and sets it to the given WtfEngine::String
				void setText(const WtfEngine::String& text);
				
				/// Returns the represented WtfEngine::String
				tString toString(bool withCursor = false);
		};
	};
	
	
	/**
	 *	WTF GUI Widgets.
	 * 	
	 * 	Implementation of basic widgets deriving from the base Widget class.
	 */
	namespace Widgets {
		/**
		 * Labels are text widgets.
		 * They also can be transparent.
		 */
		class Label: public Widget {
			private:
				WtfEngine::String	mCaption;
				bool				mTransparent;
				tFont::tRef			mFont;
				
				// Paint function
				void Paint(float depthChange);
						
			public:
				// De/constructors
				Label(const WtfEngine::String& caption, const tFont::tRef& font = tFont::Get("v_gui_font"), bool transparent = true);
				~Label();
				
				void ExpandToText();
				
				// Properties
				const WtfEngine::String& getCaption() const {
					return mCaption;
				};
				void setCaption(const WtfEngine::String& s){
					mCaption = s;
				};

				const tFont::tRef& getFont() const {
					return mFont;
				};
				void setFont(const tFont::tRef& font) {
					mFont = font;
				};
				
				// Reference
				typedef WtfEngine::GcReference<Label>		tRef;
		};
		
		class Button : public virtual IInput, public Label {
			private:
				WtfEngine::Functor::tRef	mrOnClick;
				Colour::tRef				mHoverColour;
				Colour::tRef				mBtnBgColour;
				
			public:
				Button(WtfEngine::Functor::tRef rOnClick,
					   tString caption, const tFont::tRef& font = tFont::Get("v_gui_font"), 
						bool transparent = false,
	  					Colour::tCacheRef bg = Colour::tCacheRef("v_gui_buttonBg"),
						Colour::tCacheRef hover = Colour::tCacheRef("v_gui_buttonBgHover"))
				: Label(caption, font, transparent), mrOnClick(rOnClick),
						mHoverColour(hover), mBtnBgColour(bg) {
					//SetBgColour(bg, false);
				};
				
				virtual void OnSelect() {
					//this->SetBgColour(mHoverColour);
				};
				
				virtual void OnDeselect() {
					//this->SetBgColour(mBtnBgColour);
				};
				
				virtual bool OnKeyPress(int key, int flags);
				virtual bool OnMouseDown(const iVector2D& vPos, WtfEngine::tMouseButton btn) {
					return true;
				};
				virtual bool OnMouseUp(const iVector2D& vPos, WtfEngine::tMouseButton btn);
				
				virtual bool OnMouseOver(const iVector2D& vPos, const iVector2D& vDelta){
					mpParent->Select(this, false);
					return true;
				};
		};
		
		
		/**
		 * InputFields are single line input elements. They have also have a 
		 * history stack (accessible currently through Ctrl+P and Ctrl+N).
		 * The default stack size is 10.
		 */
		class InputField : public virtual IInput, public Widget {
			private:
				Utils::StringBuffer*		buffer;
				tFont::tRef					mFont;
				
				// History stack
				std::vector<WtfEngine::String>			mHistory;
				int							mHistoryPos;
				
				// Paint
				void Paint(float depthChange);
			
			public: 
				// De/constructors
				InputField(const tFont::tRef& font);
				~InputField();
				
				// Properties/Actions
				/// returns current text
				WtfEngine::String getText() { return buffer->toString();	};
				
				/// sets the input field to given text
				void setText(tString text) { buffer->setText(text); }
				
				/// pushes current text to history
				void PushHistory();
				
				// Event handlers
				bool OnKeyPress(int key, int flags);
				bool OnMouseDown(const iVector2D& vPos, WtfEngine::tMouseButton btn);

				// Reference
				typedef WtfEngine::GcReference<InputField>	tRef;
		};
		
		/**
		 * Log fields are simplified non-editable Text Fields. As the name suggests,
		 * they are used for logging purposes, i.e. it can receive text but is otherwise
		 * not editable.
		 */
		class LogField : public Widget {
			private:
				std::vector<WtfEngine::String>		mLogRoll;		///< Log entries
				tFont::tRef				mFont;			///< Font used
				int						mMaxLines;		///< Maximum number of lines
				
				// Paint
				void Paint(float depthChange);
	
			public:
				// De/constructors
				LogField(int maxlines, const tFont::tRef& font);
				~LogField();
				
				/// Dumps the message into the log field
				void Dump(const WtfEngine::String& message);	
				void Dump(const char* message);	
				
				/// Takes the last entry and appends the passed message to it
				void Append(const WtfEngine::String& message);
				
				/// Erases the log
				void Clear();
				
				// Reference
				typedef WtfEngine::GcReference<LogField>	tRef;
		};

		/**
		 * Displays a scaled image (from texture).
		 **/
		class Image : public Widget {
			WtfEngine::Texture::tCacheRef	mrTexture;
			bool mbNeedsFlip;

			public:
				Image(const WtfEngine::Texture::tCacheRef& rTex);

				virtual void Paint(float d);

				inline WtfEngine::Texture::tRef getImage() const {
					return mrTexture.getRef();
				};
				inline void setImage(const WtfEngine::Texture::tCacheRef& rTex) {
					mrTexture = rTex;
				};

			GC_AUTOSIZE(Image);
		};
	};
};


#endif
